﻿using Microsoft.Practices.Unity.Utility;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.SessionState;

namespace Artech.Core
{
    /// <summary>
    ///  A context provider using <see cref="HttpSessionState"/> as the conext storage.
    /// </summary>
    public class SessionStateContextProvider: IContextProvider
    {
        private const string KeyOfContext = "Artech.Core.ApplicationContext";

        /// <summary>
        /// Gets the backup provider used when current <see cref="HttpContext"/> is not available.
        /// </summary>
        /// <value>
        /// The backup provider.
        /// </value>
        public virtual IContextProvider BackupProvider { get; private set; }

        /// <summary>
        /// Determine whether to use backup context provider.
        /// </summary>
        /// <returns>A <see cref="bool"/> indicating whether to use backup context provider.</returns>
        public virtual bool UsesBackupProvider()
        {
            return HttpContext.Current == null || HttpContext.Current.Session == null;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SessionStateContextProvider"/> class.
        /// </summary>
        public SessionStateContextProvider()
        {
            this.BackupProvider = new ThreadStaticContextProvider();
        }

        /// <summary>
        /// Gets the context items.
        /// </summary>
        /// <returns>
        /// A <see cref="ContextItemCollection" /> including all of <see cref="ContextItem" />.
        /// </returns>
        public ContextItemCollection GetContextItems()
        {
            if (!this.UsesBackupProvider())
            {
                ContextItemCollection contextItems = HttpContext.Current.Session[KeyOfContext] as ContextItemCollection;
                if (null == contextItems)
                {
                    contextItems = new ContextItemCollection();
                    HttpContext.Current.Session[KeyOfContext] = contextItems;
                }
                return contextItems;
            }
            return this.BackupProvider.GetContextItems();
        }

        /// <summary>
        /// Sets the context items.
        /// </summary>
        /// <param name="items">A <see cref="ContextItemCollection" />.</param>
        public void SetContextItems(ContextItemCollection items)
        {
            Guard.ArgumentNotNull(items, "items");
            if (!this.UsesBackupProvider())
            {
                HttpContext.Current.Session[KeyOfContext] = items;
            }
            else
            {
                this.BackupProvider.SetContextItems(items);
            }
        }
    }
}
